package com.derbysoft.ota.application.translator.rq;

import java.util.Date;
import java.util.List;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.application.util.Booleans;
import com.derbysoft.ota.application.util.Calendars;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType;
import com.derbysoft.ota.interfaces.protocol._2009a.PersonNameType;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType.Address;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType.Email;
import com.derbysoft.ota.interfaces.protocol._2009a.CustomerType.Telephone;
import com.derbysoft.remote.dswitch.generic.constants.CountryType;
import com.derbysoft.remote.dswitch.generic.constants.GenderType;
import com.derbysoft.remote.dswitch.generic.dto.CustomerDTO;
import com.derbysoft.remote.dswitch.generic.dto.EmailDTO;
import com.derbysoft.remote.dswitch.generic.dto.PersonNameDTO;
import com.derbysoft.remote.dswitch.generic.dto.TelephoneDTO;
import com.google.common.base.Function;
import com.google.inject.Inject;
import com.googlecode.functionalcollections.FunctionalIterables;

public class GuestTranslator implements Translator<CustomerType, CustomerDTO> {
	
	private Translator<Address, String> addressTranslator;
	private Translator<Telephone, TelephoneDTO> telephoneTranslator;
	
	@Inject
	public GuestTranslator(
		Translator<Address, String> addressTranslator,
		Translator<Telephone, TelephoneDTO> telephoneTranslator) {
		
		this.addressTranslator = addressTranslator;
		this.telephoneTranslator = telephoneTranslator;
	}

	@Override
	public CustomerDTO translate(CustomerType source) {
		CustomerDTO dest = new CustomerDTO();
		dest.setAddresses(addresses(source));
		dest.setBirthDate(birthDate(source));
		dest.setCountry(country(source));
		dest.setEmails(emails(source));
		dest.setGender(gender(source));
		dest.setPersonName(personName(source));
		dest.setPetInfo(petInfo(source));
		dest.setTelephones(telephones(source));
		dest.setVipIndicator(vipIndicator(source));
		return dest;
	}

	private boolean vipIndicator(CustomerType source) {
		return Booleans.toPrimitive(source.isVIPIndicator());
	}

	private List<TelephoneDTO> telephones(CustomerType source) {
		return FunctionalIterables.make(source.getTelephone()).map(
				new Function<Telephone, TelephoneDTO>() {
					public TelephoneDTO apply(Telephone from) {
						return telephoneTranslator.translate(from);
					}
		}).toList();
	}

	private List<String> petInfo(CustomerType source) {
		return source.getPetInfo();
	}

	private GenderType gender(CustomerType source) {
		if (source.getGender() == null) {
			return GenderType.UNKNOWN;
		}
		return GenderType.valueOf(source.getGender().name());
	}

	private List<EmailDTO> emails(CustomerType source) {
		return FunctionalIterables.make(source.getEmail()).map(
				new Function<Email, EmailDTO>() {
					public EmailDTO apply(Email from) {
						return new EmailDTO(from.getValue());
					}
		}).toList();
	}

	private CountryType country(CustomerType source) {
		if (source.getCitizenCountryName().isEmpty()) {
			return null;
		}
		return CountryType.valueOf(source.getCitizenCountryName().iterator().next().getCode());
	}


	private Date birthDate(CustomerType source) {
		if (source.getBirthDate() == null) {
			return null;
		}
		return Calendars.getDateOfGMT0(source.getBirthDate());
	}

	private PersonNameDTO personName(CustomerType source) {
		PersonNameType otaPersonName = FunctionalIterables.make(source.getPersonName()).messagedIterator("PersonName required.").next();
		PersonNameDTO switchPersonName = new PersonNameDTO();
		switchPersonName.setSurname(otaPersonName.getSurname());
		switchPersonName.setGivenName(FunctionalIterables.make(otaPersonName.getGivenName()).messagedIterator("GivenName required.").next());
		if (!otaPersonName.getNamePrefix().isEmpty()) {
			switchPersonName.setNamePrefix(otaPersonName.getNamePrefix().iterator().next());
		}
		return switchPersonName;
	}

	private List<String> addresses(CustomerType source) {
		return FunctionalIterables.make(source.getAddress()).map(
			new Function<Address, String>() {
				public String apply(Address from) {
					return addressTranslator.translate(from);
				}
			}
		).toList();
	}


}
